package vip.xiaonuo.biz.modular.nccAi.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;
import vip.xiaonuo.biz.modular.nccAi.entity.BankReceiptInfo;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.dev.api.DevConfigApi;


import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


/**
 * ClassName:FileUtil
 * Description:
 *
 * @Author:薛守立
 * @CreateTime:2025/5/28 14:40
 */
@Slf4j
public class FileUtil {

    // 获取系统默认解压目录
    private static final String UNZIP_PATH = "UNZIP_PATH";
    private static final String SPLIT_PATH = "SPLIT_PATH";

    private static final Pattern AMOUNT_PATTERN = Pattern.compile("金额[:：]\\s*([\\d\\s,.-]+)");
    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static String getPath(String type){
        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMM-HH_mm_ss");
        String path = "";
        DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class);
        if(type.equals("unzip")){
            path = devConfigApi.getValueByKey(UNZIP_PATH);
            if(ObjectUtil.isEmpty(path)) {
                throw new CommonException("文件解压路径错误");
            }
        }

        if(type.equals("split")){
            path = devConfigApi.getValueByKey(SPLIT_PATH);
            if(ObjectUtil.isEmpty(path)) {
                throw new CommonException("文件拆分路径错误");
            }
        }

        return path+sdf.format(new Date());
    }


    /**
     * PDF文件拆分
     *
     * @param filePath 拆分的文件路径
     * @param outputPath 输出的文件路径
     * @Return
     */
    public static List<String> SplitPages (String filePath, String outputPath, String fileName) throws IOException {
        File inputFile = new File(filePath);
        File outputDir = new File(outputPath);
        List<String> res = new ArrayList<>();
        if(!outputDir.exists()) outputDir.mkdir();
        try (PDDocument originalDoc = Loader.loadPDF(inputFile)) {
            PDFRenderer renderer = new PDFRenderer(originalDoc);
            int pageCount = originalDoc.getNumberOfPages();

            for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
                // 渲染原始页面为图像（400 DPI）
                BufferedImage fullImage = renderer.renderImage(pageIndex, 3.0f);
                int originalHeight = fullImage.getHeight();

                // 计算分割区域
                java.util.List<Rectangle> splitRegions = calculateSplitRegions(originalHeight);

                // 处理每个分割区域
                for (int i = 0; i < splitRegions.size(); i++) {
                    Rectangle region = splitRegions.get(i);
                    BufferedImage segment = fullImage.getSubimage(
                            0,
                            region.y,
                            fullImage.getWidth(),
                            region.height
                    );

                    // 跳过空白内容
                    if (!isImageEmpty(segment)) {
                        // 创建新PDF文档
                        try (PDDocument segmentDoc = new PDDocument()) {
                            PDPage newPage = new PDPage(new PDRectangle(
                                    segment.getWidth(),
                                    segment.getHeight()
                            ));
                            segmentDoc.addPage(newPage);

                            // 将图像绘制到新页面
                            try (PDPageContentStream contentStream = new PDPageContentStream(
                                    segmentDoc,
                                    newPage,
                                    PDPageContentStream.AppendMode.APPEND,
                                    true,
                                    true)) {

                                PDImageXObject pdImage = LosslessFactory.createFromImage(segmentDoc, segment);
                                contentStream.drawImage(pdImage, 0, 0);
                            }

                            // 保存文件（文件名示例：out_page1_part1.pdf）
                            File outputFile = new File(outputDir, String.format(
                                    fileName+"out_%d_%d.pdf",
                                    pageIndex + 1,
                                    i + 1
                            ));
                            segmentDoc.save(outputFile);
                            res.add(outputFile.getPath());
                            System.out.println("生成文件: " + outputFile.getName());
                        }
                    }
                }
            }
            System.out.println("PDF分割完成！输出目录：" + outputDir.getAbsolutePath());
            return res;

        } catch (IOException e) {
            System.err.println("处理过程中发生错误:");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 计算原始高度，用于分隔pdf页面
     *
     * @param originalHeight
     * @return
     */
    private static java.util.List<Rectangle> calculateSplitRegions(int originalHeight) {
        java.util.List<Rectangle> regions = new ArrayList<>();
        int first40 = (int) (originalHeight * 0.4);
        int second40 = (int) (originalHeight * 0.4);
        int last20 = originalHeight - first40 - second40;

        regions.add(new Rectangle(0, 0, 0, first40));
        regions.add(new Rectangle(0, first40, 0, second40));
        regions.add(new Rectangle(0, first40 + second40, 0, last20));

        return regions;
    }

    /**
     * 判断页面内容是否为空
     * @param image
     * @return
     */
    private static boolean isImageEmpty(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();

        // 快速检测策略：采样检测+提前终止
        final int sampleStep = 10;
        for (int y = 0; y < height; y += sampleStep) {
            for (int x = 0; x < width; x += sampleStep) {
                int rgb = image.getRGB(x, y);
                if (rgb != Color.WHITE.getRGB() &&
                        new Color(rgb).getAlpha() > 50) { // 忽略半透明像素
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 返回string字符串对象
     * @param filePath
     * @return
     * @throws IOException
     */
    public static BankReceiptInfo readQRCodeFromPDF(String filePath) throws IOException {
        try (PDDocument document = Loader.loadPDF(new File(filePath))) {
            // 设置文档信息以确保正确解析
            PDDocumentInformation info = document.getDocumentInformation();
            info.setProducer("PDFBox 3.0.1");

            // 渲染PDF为图像 (300 DPI)
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            BufferedImage image = pdfRenderer.renderImageWithDPI(0, 150);

            // 使用ZXing解析二维码
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
                    new BufferedImageLuminanceSource(image)));
            MultiFormatReader reader = new MultiFormatReader();
            Result result = reader.decode(bitmap);

            // 改进的编码处理
            String rawResult = result.getText();
            // 尝试自动检测编码
            if (looksLikeUTF8(rawResult)) {
                return parseQrCodeText(rawResult);
            }
            // 尝试GBK编码
            try {
                return parseQrCodeText(new String(rawResult.getBytes(StandardCharsets.ISO_8859_1), "GBK")) ;
            } catch (Exception e) {
                // 默认使用UTF-8
                return parseQrCodeText(new String(rawResult.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
            }
        } catch (NotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将识别结果转化为javaBean
     * @param text
     */
    private static BankReceiptInfo parseQrCodeText(String text) {
        List<String> lines = Arrays.asList(text.split("\\r?\\n"));
        Map<String, String> fieldMap = extractFields(lines);

        BankReceiptInfo.BankReceiptInfoBuilder builder = BankReceiptInfo.builder();

        builder.receiptType(fieldMap.get("兰州银行网上银行电子回单"))
                .payerName(fieldMap.get("付款人户名"))
                .payerAccount(fieldMap.get("付款人账号"))
                .currency(fieldMap.get("币种"))
                .transactionType(fieldMap.get("交易类型"))
                .transactionChannel(fieldMap.get("交易渠道"))
                .transactionDate(fieldMap.get("记账日期"));

        // 特殊处理金额和日期
        String amountStr = fieldMap.get("金额");
        if (amountStr != null) {
            builder.amount(parseAmount(amountStr));
        }
        String dateStr = fieldMap.get("记账日期");
        if (dateStr != null) {
            builder.transactionDate(parseDate(dateStr));
        }

        return builder.build();
    }

    // 简单的UTF-8编码检测
    private static boolean looksLikeUTF8(String s) {
        try {
            byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
            // 检查是否包含UTF-8多字节字符
            for (int i = 0; i < bytes.length; i++) {
                byte b = bytes[i];
                if ((b & 0x80) != 0) { // 非ASCII字符
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }


    private static Map<String, String>  extractFields(List<String> lines) {
        Map<String, String> fieldMap = new LinkedHashMap<>();
        StringBuilder currentValue = new StringBuilder();
        String currentKey = null;

        for (String line : lines) {
            line = line.trim();
            if (line.isEmpty()) continue;

            // 检查是否是新的键值对
            if (line.contains("：") || line.contains(":")) {
                String[] parts = line.split("[:：]", 2);
                if (parts.length == 2) {
                    // 保存上一个键值对
                    if (currentKey != null) {
                        fieldMap.put(currentKey, currentValue.toString().trim());
                    }
                    currentKey = parts[0].trim();
                    currentValue.setLength(0);
                    currentValue.append(parts[1].trim());
                } else {
                    // 只有键没有值
                    if (currentKey != null) {
                        fieldMap.put(currentKey, currentValue.toString().trim());
                    }
                    currentKey = line;
                    currentValue.setLength(0);
                }
            } else {
                // 延续上一行的值
                if (currentKey != null) {
                    currentValue.append(" ").append(line);
                }
            }
        }

        // 保存最后一个键值对
        if (currentKey != null) {
            fieldMap.put(currentKey, currentValue.toString().trim());
        }

        return fieldMap;
    }

    private static BigDecimal parseAmount(String amountStr) {
        // 移除所有非数字和小数点字符
        String cleaned = amountStr.replaceAll("[^\\d.]", "");
        try {
            return new BigDecimal(cleaned);
        } catch (NumberFormatException e) {
            System.err.println("金额解析失败: " + amountStr);
            return BigDecimal.ZERO;
        }
    }

    private static String parseDate(String dateStr) {
        // 移除所有非数字和小数点字符
        String[]  dateList = dateStr.split(" ");
        return dateList[0];
    }

    private static LocalDateTime parseDateTime(String dateStr) {
        try {
            return LocalDateTime.parse(dateStr, DATE_FORMAT);
        } catch (Exception e) {
            System.err.println("日期解析失败: " + dateStr);
            return null;
        }
    }
}
